#ifndef __I_NGISMODEL_MODEL_BEHAVIOR_H__
#define __I_NGISMODEL_MODEL_BEHAVIOR_H__

#include "../udx/INxUnknown.h"
#include "../udx/UdxDataSchemaApi.h"
#include <string>
#include <vector>

namespace NGIS
{
	namespace Model
	{
		enum EModelEventType
		{
			EMET_RESPONSE,
			EMET_NORESPONSE,
			EMET_CONTROL
		};

		enum EModelStateType
		{
			EMST_BASIC,
			EMST_GROUP
		};

		enum EModelDatasetItemType
		{
			EMDIT_INTERNAL,
			EMDIT_EXTERNAL,
			EMDIT_RAW
		};

		struct ModelDatasetItem
		{
			ModelDatasetItem()
			{
				datasetItem=NULL;
				datasetName="";
				datasetItemType = EMDIT_INTERNAL;
				datasetItemDescription = "";
				externalId = "";
			}

			bool compareOther(ModelDatasetItem pDatasetItem)
			{
				if (datasetItem==NULL && pDatasetItem.datasetItem !=NULL 
					|| datasetItem !=NULL && pDatasetItem.datasetItem==NULL)
				{
					return false;
				}
				if (datasetItem && pDatasetItem.datasetItem)
				{
					if (datasetItem->compareOther(pDatasetItem.datasetItem)==false)
						return false;
				}
				if (datasetName != pDatasetItem.datasetName)
				{
					return false;
				}
				if (datasetItemType != pDatasetItem.datasetItemType)
				{
					return false;
				}
				if (datasetItemDescription != pDatasetItem.datasetItemDescription)
				{
					return false;
				}
				if (externalId != pDatasetItem.externalId)
				{
					return false;
				}

				return true;
			}

			NGIS::Data::Schema::IUdxDatasetSchema* datasetItem;
			std::string datasetName;
			EModelDatasetItemType datasetItemType;
			std::string datasetItemDescription;
			std::string externalId;
		};

		struct ModelEvent
		{
			ModelEvent()
			{
				eventName = "";
				eventType = EMET_CONTROL;
				eventDescription = "";
				datasetReference = "unknown";
				parameterDescription = "";
				optional = false;
			}

			bool compareOther(ModelEvent pEvent)
			{
				if (eventName!=pEvent.eventName)
				{
					return false;
				}
				if (eventType != pEvent.eventType)
				{
					return false;
				}
				if (eventDescription != pEvent.eventDescription)
				{
					return false;
				}
				if (datasetReference != pEvent.datasetReference)
				{
					return false;
				}
				if (parameterDescription != pEvent.parameterDescription)
				{
					return false;
				}
				if (optional != pEvent.optional)
				{
					return false;
				}

				return true;
			}

			std::string eventName;
			EModelEventType eventType;
			std::string eventDescription;
			std::string datasetReference;
			std::string parameterDescription;
			bool optional;
		};

		struct ModelState
		{
			ModelState()
			{
				stateId = "";
				stateName = "State Name";
				stateType = EMST_BASIC;
				stateDecription = "";
				modelEvents.clear();
			}

			bool compareOther(ModelState pState)
			{
				if (stateId != pState.stateId)
				{
					return false;
				}
				if (stateName != pState.stateName)
				{
					return false;
				}
				if (stateType != pState.stateType)
				{
					return false;
				}
				if (stateDecription != pState.stateDecription)
				{
					return false;
				}
				if (modelEvents.size() != pState.modelEvents.size())
				{
					return false;
				}
				for (int iEvent = 0; iEvent<modelEvents.size(); iEvent++)
				{
					ModelEvent event1 = modelEvents[iEvent];
					ModelEvent event2 = pState.modelEvents[iEvent];
					if (event1.compareOther(event2)==false)
						return false;
				}
				return true;
			}

			std::string stateId;
			std::string stateName;
			EModelStateType stateType;
			std::string stateDecription;
			std::vector<ModelEvent> modelEvents;
		};

		struct ModelStateTransition
		{
			ModelStateTransition()
			{
			}

			bool compareOther(ModelStateTransition pTrans)
			{
				if (fromState.compareOther(pTrans.fromState)==false)
				{
					return false;
				}
				if (toState.compareOther(pTrans.toState)==false)
				{
					return false;
				}
				return true;
			}
			ModelState fromState;
			ModelState toState;
		};

		class IModelBehavior : public INxUnknown
		{
		public:
			//////////////////////////////////////Dataset Declarations////////////////////////////////////
			virtual bool addModelDatasetItem(ModelDatasetItem& pDataset) = 0;

			virtual bool removeModelDatasetItem(ModelDatasetItem& pDataset) = 0;

			virtual int getModelDatasetItemCount() = 0;

			virtual bool getModelDatasetItem(int idx, ModelDatasetItem& pDataset) = 0;

			virtual bool getModelDatasetItem(std::string pName, ModelDatasetItem& pDataset) = 0;

			virtual bool updateModelDatasetItem(int idx, ModelDatasetItem& pDataset) = 0;

			//////////////////////////////////////Model State Group////////////////////////////////////
			virtual bool addModelState(ModelState& pState) = 0;

			virtual bool removeModelState(ModelState& pState) = 0;

			virtual int getModelStateCount() = 0;

			virtual bool getModelState(int idx, ModelState& pState) = 0;

			virtual bool getModelState(std::string pStateId, ModelState& pState) = 0;

			virtual bool updateModelState(int idx, ModelState& pState) = 0;

			virtual bool updateModelState(std::string pStateId, ModelState& pState) = 0;

			/////////////////////////////////////Model State Transition/////////////////////////////////////
			virtual bool addModelStateTransition(std::string pFromStateId, std::string pToStateId) = 0;

			virtual bool addModelStateTransition(ModelState& pFromState, ModelState& pToState) = 0;

			virtual bool removeModelStateTransition(std::string pFromStateId, std::string pToStateId) = 0;

			virtual bool removeModelStateTransition(ModelState& pFromState, ModelState& pToState) = 0;

			virtual int getModelStateTransitionCount() = 0;

			virtual bool getModelStateTransition(int idx, ModelState& pFromState, ModelState& pToState) = 0;

			virtual bool getModelStateTransition(int idx, ModelStateTransition& pStateTransition) = 0;

			virtual bool existModelStatetTransition(std::string pFromStateId, std::string pToStateId) = 0;

			virtual bool existModelStatetTransition(ModelState& pFromState, ModelState& pToState) = 0;

			virtual bool updateModelStateTransition(int idx, std::string pFromStateId, std::string pToStateId) = 0;

			//////////////////////////////////////////////////////////////////////////
			virtual bool compareOther(IModelBehavior* pBehavior, std::string& obj, std::string& name) = 0;
		};
	}
}

#endif